package com.atguigu.gmall.order.service.impl;

import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.AuthContextHolder;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.PaymentStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderService;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

@Service
public class OrderServiceImpl implements OrderService {


    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RabbitService rabbitService;

    @Value("${ware.url}")
    private String wareUrl;


    /**
     * 添加订单数据
     *
     * @param orderInfo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveOrderInfo(OrderInfo orderInfo) {
//  orderInfo orderDetail
        //  total_amount ，order_status user_id out_trade_no trade_body operate_time expire_time process_status
        // 设置订单数据
        orderInfo.sumTotalAmount();
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        //  这个第三方交易编号不能重复！
        String outTradeNo = "ATGUIGU" + System.currentTimeMillis() + "" + new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        //  把订单明细中的各个商品名称拼接起来。
        orderInfo.setTradeBody("购买小分队.....");
        orderInfo.setOperateTime(new Date());
        //  设置过期时间：
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 1);
        orderInfo.setExpireTime(calendar.getTime());
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        orderInfoMapper.insert(orderInfo);


        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        if (orderDetailList != null) {
            // 遍历将订单明细加入到数据库
            for (OrderDetail orderDetail : orderDetailList) {

                orderDetail.setOrderId(orderInfo.getId());
                orderDetailMapper.insert(orderDetail);
            }
        }

        //发送延迟队列，如果定时未支付，取消订单
        rabbitService.sendDelayMessage(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL, MqConst.ROUTING_ORDER_CANCEL, orderInfo.getId(), MqConst.DELAY_TIME);


        return orderInfo.getId();
    }

    /**
     * 生成流水号
     * @param userId
     * @return
     */
    @Override
    public String getTradeNo(String userId) {
        // 生成一个key
        // 定义key
        String tradeNoKey = "user:" + userId + ":tradeCode";

        // 生成一个流水号
        String tradeNo = UUID.randomUUID().toString().replace("-","");

        // 将流水号存入到缓存中
        this.redisTemplate.opsForValue().set(tradeNoKey,tradeNo);

        return tradeNo;
    }

    /**
     * 比较流水号
     * @param userId
     * @param tradeCodeNo
     * @return
     */
    @Override
    public boolean checkTradeCode(String userId, String tradeCodeNo) {

        // 生成key
        String tradeNoKey = "user:" + userId + ":tradeCode";
        // 从redis中获取
        String  oldTradeCodeNo = (String) this.redisTemplate.opsForValue().get(tradeNoKey);

        return tradeCodeNo.equals(oldTradeCodeNo);
    }

    /**
     * 删除流水号
     * @param userId
     */
    @Override
    public void deleteTradeNo(String userId) {
// 生成key
        String tradeNoKey = "user:" + userId + ":tradeCode";
        //删除
        this.redisTemplate.delete(tradeNoKey);
    }

    /**
     * 库存校验
     * @param skuId
     * @param skuNum
     * @return
     */
    @Override
    public boolean checkStock(Long skuId, Integer skuNum) {
//  远程调用  wareUrl = http://localhost:9001/hasStock?skuId=10221&num=2
        String result = HttpClientUtil.doGet(wareUrl + "/hasStock?skuId=" + skuId + "&num=" + skuNum);

        return "1".equals(result);
    }


    /**
     * 分页查询我的订单数据
     * @param orderInfoPage
     * @param userId
     * @return
     */
    @Override
    public IPage<OrderInfo> getPage(Page<OrderInfo> orderInfoPage, String userId) {
        IPage<OrderInfo> iPage = orderInfoMapper.selectPages(orderInfoPage, userId);
        iPage.getRecords().stream().forEach(item -> {
            item.setOrderStatusName(OrderStatus.getStatusNameByStatus(item.getOrderStatus()));
        });

        return iPage;
    }

    /**
     * 取消订单接口
     * @param orderId
     */
    @Override
    public void execExpiredOrder(String orderId) {

        // 先根据orderid查询是否有这个订单
        OrderInfo orderInfo = this.getByIdOrderInfo(orderId);
        if (orderInfo != null){
            orderInfo.setProcessStatus(ProcessStatus.CLOSED.name());
            orderInfo.setOrderStatus(ProcessStatus.CLOSED.name());
            orderInfoMapper.updateById(orderInfo);
        }

    }

    /**
     * 根据订单id查询订单详情
     * @param orderId
     * @return
     */
    @Override
    public OrderInfo getByIdOrderInfo(String orderId) {
        // 判断
        if (!StringUtils.isEmpty(orderId)){
            OrderInfo orderInfo = orderInfoMapper.selectById(Long.parseLong(orderId));
            if (orderInfo != null){
                QueryWrapper<OrderDetail> orderDetailQueryWrapper = new QueryWrapper<>();
                orderDetailQueryWrapper.eq("order_id",orderId);
                List<OrderDetail> orderDetails = orderDetailMapper.selectList(orderDetailQueryWrapper);
                orderInfo.setOrderDetailList(orderDetails);
            }

            return orderInfo;
        }
        return null;
    }

    @Override
    public void updOrder(String orderId, String paid) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(Long.parseLong(orderId));
        orderInfo.setOrderStatus(paid);
        orderInfo.setProcessStatus(ProcessStatus.PAID.name());
        orderInfoMapper.updateById(orderInfo);
    }
}